package router

import (
	"fmt"
	"log"
	"net"

	"gin-gateway/core/dao"
	"gin-gateway/middleware/grpc_proxy_middleware"
	"gin-gateway/reverse_proxy"
	"google.golang.org/grpc"
	"google.golang.org/grpc/encoding"
	"gin-gateway/example/gateway_demo/otherProxy/grpc_proxy"
)

var grpcServerList []*warpGrpcServer

type warpGrpcServer struct {
	Addr string
	*grpc.Server
}

func GrpcProxyServerRun() {
	serviceList := dao.ServiceManagerHandler.GetGrpcServiceList()
	for _, serviceItem := range serviceList {
		tempItem := serviceItem
		go func(serviceDetail *dao.ServiceDetail) {
			addr := fmt.Sprintf(":%d", serviceDetail.GRPCRule.Port)
			lb, err := dao.LoadBalancerManager.GetLoadBalancer(serviceDetail)
			if err != nil {
				log.Fatalf("[INFO] GetTcpLoadBalancer %v err:%v\n", addr, err)
				return
			}

			lis, err := net.Listen("tcp", addr)
			if err != nil {
				log.Fatalf("[INFO] GrpcListen %v err:%v\n", addr, err)
			}

			encoding.RegisterCodec(grpc_proxy.Codec()) // 设置grpcServer 全局使用编解码
			s := grpc.NewServer(grpc.ChainStreamInterceptor(
				grpc_proxy_middleware.GrpcFlowCountMiddleware(serviceDetail),
				grpc_proxy_middleware.GrpcFlowLimitMiddleware(serviceDetail),
				// grpc_proxy_middleware.GrpcCircuitBreakMiddleware(serviceDetail), // 熔断
				grpc_proxy_middleware.GrpcJwtAuthTokenMiddleware(serviceDetail), // 租户使用 jwt
				grpc_proxy_middleware.GrpcJwtFlowCountMiddleware(serviceDetail),
				grpc_proxy_middleware.GrpcJwtFlowLimitMiddleware(serviceDetail),
				grpc_proxy_middleware.GrpcWhiteAndBlackListMiddleware(serviceDetail),
				grpc_proxy_middleware.GrpcHeaderTransferMiddleware(serviceDetail),
			), grpc.UnknownServiceHandler(reverse_proxy.NewGrpcLoadBalanceHandler(lb))) // 未定义的服务请求都会转给它处理

			grpcServerList = append(grpcServerList, &warpGrpcServer{
				Addr:   addr,
				Server: s})
			log.Printf("[INFO] GrpcProxyServerRun %v\n", addr)
			if err := s.Serve(lis); err != nil {
				log.Fatalf("[INFO] GrpcProxyServerRun %v err:%v\n", addr, err)
			}
		}(tempItem)
	}
}

func GrpcProxyServerStop() {
	for _, grpcServer := range grpcServerList {
		grpcServer.GracefulStop()
		log.Printf("[INFO] GrpcProxyServerStop %v stopped\n", grpcServer.Addr)
	}
}
